---
title: Retrieve the accessible policy list for a user
summary: Builds the set of policies a user may select, using a different query per user type (agent, group, loss-control consultant, fee auditor).
status: draft
owner: SAIF Corporation
last_reviewed: 2026-09-01
library: SAIF.Business.View.Policy
reference_type: embedded
operation_id: op-08-retrieve-accessible-policy-list
trigger: Caller reads PolicySecurity.PolicyList
---

# Retrieve the accessible policy list for a user

Builds the list of policies a given user is permitted to select from, dispatching to a different data source per user type: group/chapter book, safety-consultant book, agent/agency online list, or fee-auditor list. Policyholder users instead derive their list from their own affiliated-policy collection.

| Field | Value |
| --- | --- |
| **Operation ID** | op-08-retrieve-accessible-policy-list |
| **Trigger** | Caller reads `clsPolicySecurity.PolicyList` |
| **Inputs** | Current `UserType`/`SecurityPrincipal` |
| **Outputs** | `List(Of strPolicyList)` — each entry has `PolicyNum`, `PolicyName`, `PolicyNameAndNumber` |
| **Primary components** | `PolicyList` property, `GetPolicyListForAgent`, `GetPolicyListforGroup`, `GetPolicyListForSafetyConsultant`, `GetPolicyListForFeeAuditor` |
| **Entry point** | `SAIF.Business.View.Policy/clsPolicySecurity.vb` |

## Steps

1. The `PolicyList` property is lazily populated (`m_PolicyList Is Nothing` guard) on first read, and dispatches on `UserType.UserType` ([BR-VP-005](../business-rules.md#br-vp-005-access-granted-per-user-access-level-matrix)):
   - `Agent` → `GetPolicyListForAgent(UserType.UserNumber, Not UserType.IsProducer())`.
   - `PolicyHolder` → builds the list directly in-memory from `PolicyDataForUser.AffiliatedPolicyCollection`, without an additional list-specific query (see [Retrieve affiliated policies (legacy)](op-09-retrieve-affiliated-policies.md)).
   - `LossControl` → `GetPolicyListForSafetyConsultant(UserType.UserNumber.ToString)`.
   - `Group` → `GetPolicyListforGroup()`.
   - `Auditor` → `GetPolicyListForFeeAuditor(UserType.UserNumber.ToString)`.
   - Any other user type leaves `m_PolicyList` unset; the getter then returns an empty `List(Of strPolicyList)`.
2. `GetPolicyListForAgent` guards on `IsNumeric(inAgentNum)` before querying; executes `cp_get_agent_online_policy_list` ([SQL-027](../sql/SQL-027-cp-get-agent-online-policy-list.md)) on the SQL Server (BDS) portal, binding `@AgentNum` and `@ForAgency` (derived from "not a producer").
3. `GetPolicyListforGroup` executes `cp_claimprofile_get_group_policy_list` ([SQL-025](../sql/SQL-025-cp-claimprofile-get-group-policy-list.md)) on the BDS portal, binding `@GroupKeyCode`, `@SpecificChapterCode`, and `@rptDate = Now`; a code comment documents a special-case group whose chapter code is a regex-like bracketed exclusion pattern (`HBA[^E]`) rather than a literal chapter letter.
4. `GetPolicyListForSafetyConsultant` executes `cp_claimprofile_get_sc_book` ([SQL-026](../sql/SQL-026-cp-claimprofile-get-sc-book.md)) on the BDS portal, binding `@losscontrol` to the user number.
5. `GetPolicyListForFeeAuditor` executes an inline-built SQL string from `GetAuditorPolicyListSQL()` ([SQL-028](../sql/SQL-028-fee-auditor-policy-list.md)) on the primary (Oracle) portal as `RequestType.ResultSet`/`CommandType.Text`, binding `VendorNum`; the SQL joins `pa_audit`, `pa_auditor`, and `policy`, filtering out cancelled/completed audits older than a rolling 60-day-forward window (`sysdate + 60`).
6. Each of the four query methods maps result rows into `strPolicyList` structures via the same `New strPolicyList(policyNum, policyName)` pattern, though the exact column names queried differ per source (`policy_number`/`policy_name` for the group/SC-book/agent queries vs. `POLICY_NUM`/`POLICY_NAME` for the auditor query).

## Process flow

```mermaid
flowchart TD
	Start(["Caller reads<br>PolicySecurity.PolicyList"]) --> A{m_PolicyList<br>already populated?}
	A -->|Yes| Return(["Return cached list"])
	A -->|No| B{User type?}
	B -->|Agent| C["cp_get_agent_online_policy_list<br>(BDS)"]
	B -->|PolicyHolder| D["Build in-memory from<br>AffiliatedPolicyCollection"]
	B -->|LossControl| E["cp_claimprofile_get_sc_book<br>(BDS)"]
	B -->|Group| F["cp_claimprofile_get_group_policy_list<br>(BDS)"]
	B -->|Auditor| G["Inline fee-auditor query<br>(Oracle)"]
	B -->|Other| H["m_PolicyList left unset"]
	C --> I["Map rows to strPolicyList"]
	D --> I
	E --> I
	F --> I
	G --> I
	I --> Return
	H --> J(["Return empty list"])
```

## Failure and edge-case behavior
- `GetPolicyListForAgent` silently produces no list (leaves `m_PolicyList` unset, so the getter returns an empty list) if `inAgentNum` is not numeric — no exception is raised.*
- A user type not covered by the `Select Case` (e.g. `SaifEmployee`, `MCO`, `MedProv`, `Bookkeeper`) receives an empty policy list from this property even though `IsPolicyValidForUser` grants those types unconditional per-policy access — the two operations are not symmetric.*
- The fee-auditor query's 60-day window uses `sysdate + 60` on both `cancel_date` and `completed_date` bounds, which reads as a forward-looking window rather than the `-60`-day lookback used in `CanAuditorAccessPolicy` for the single-policy authorization check — the two auditor-access queries do not use an identical time window.*

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources
- `SAIF.Business.View.Policy/clsPolicySecurity.vb`
